package com.swak.fx.support;

import java.util.concurrent.TimeUnit;

import com.swak.exception.InvokeException;
import com.swak.fx.support.ui.UIController;
import com.swak.fx.support.ui.UILifecycle;
import com.swak.reactivex.threads.TimerContext.ScheduledTimerTask;

import javafx.scene.layout.Pane;

/**
 * 基础的组件
 * 
 * @author 618lf
 */
public abstract class AbstractComp extends AbstractView implements Lifecycle, UILifecycle, UIController {

	protected final AbstractPage parent;

	public AbstractComp() {
		this(null);
	}

	public AbstractComp(AbstractPage parent) {
		this.parent = parent;
	}

	// ================================================================================
	// Worker
	// ================================================================================
	@Override
	protected void $run(Runnable task) {
		if (this.parent != null) {
			this.parent.$context.execute(task);
		} else {
			super.$run(task);
		}
	}
	
	// ================================================================================
	// Timer
	// ================================================================================
	@Override
	protected ScheduledTimerTask $setTimeOut(Runnable task, long delayMs) {
		if (this.parent != null) {
			return this.parent.$timer.schedule(() -> this.parent.$context.execute(task), delayMs,
					TimeUnit.MILLISECONDS);
		}
		return super.$setTimeOut(task, delayMs);
	}

	@Override
	protected ScheduledTimerTask $setTimeInterval(Runnable task, long period) {
		if (this.parent != null) {
			return this.parent.$timer.scheduleAtFixedRate(() -> this.parent.$context.execute(task), period,
					TimeUnit.MILLISECONDS);
		}
		return super.$setTimeInterval(task, period);
	}

	// ================================================================================
	// Page 事件
	// ================================================================================
	protected void $emitInPage(String event) {
		this.parent.$emit(event, null);
	}

	protected void $emitInPage(String event, Object param) {
		this.parent.$emit(event, param);
	}

	@Override
	public void destory() {
		super.destory();
		try {
			if (this.root instanceof Pane) {
				((Pane) this.root).getChildren().clear();
			}
		} catch (Exception e) {
		}
	}

	// ================================================================================
	// New Comp (这里没办法在子类中获取实际的调用类)
	// ================================================================================
	public static <T extends AbstractComp> T New(Class<T> theClass) {
		try {
			T t = theClass.getDeclaredConstructor().newInstance();
			t.init();
			return t;
		} catch (Exception e) {
			throw new InvokeException(e);
		}
	}

	private static Class<?>[] Classes = new Class[] { AbstractPage.class };

	public static <T extends AbstractComp> T New(Class<T> theClass, AbstractPage parent) {
		try {
			T t = theClass.getDeclaredConstructor(Classes).newInstance(new Object[] { parent });
			t.init();
			return t;
		} catch (Exception e) {
			throw new InvokeException(e);
		}
	}
}
